/*
   If you plan to use this store with a widget that is a Dojo Data consumer, then you need
   to use dojo.data.ObjectStore wrapper around this store.
   More info: http://dojotoolkit.org/reference-guide/dojo/data/ObjectStore.html
*/


define(
   [
      'dojo/_base/declare',
      'dojo/Deferred',
      'dojo/store/JsonRest',
      'dijit/Destroyable'
   ],
   function(declare, Deferred, Store, Destroyable)
   {
      return declare([Store, Destroyable],
      {
         mObjectStoreWrapper: null, // This is used for backwards compatability with old stores who need a ObjectStore wrapper to use this store
         target:              null,
         idProperty:          'Id',
         childrenAttr:        'children',
         labelAttr:           'Name',
         sortParam:           'sortBy',
         
         constructor:function (args)
         {
            // Call Super
            dojo.safeMixin(this, args);
         },
         postscript: function(args)
         {
            // Called after constructors
            this.inherited(arguments);
         },
         destroy: function()
         {
            this.inherited(arguments);
         },
         setObjectStoreWrapper: function(pWrapper)
         {
            this.mObjectStoreWrapper = pWrapper;
         },

         mayHaveChildren: function(pObject){
            // see if it has a children property
            return this.childrenAttr in pObject && pObject[this.childrenAttr];
         },
         getChildren: function(pObject, onComplete, onError){
            // retrieve the full copy of the pObject
            this.get(pObject[this.idProperty]).then(dojo.hitch(this, function(fullObject)
            {
               // copy to the original pObject so it has the children array as well.
               pObject[this.childrenAttr] = fullObject[this.childrenAttr];
               // now that full pObject, we should have an array of children
               onComplete(fullObject[this.childrenAttr]);
            }), function(error)
            {
               // an error occurred, log it, and indicate no children
               console.error(error);
               onComplete([]);
            });
         },
         getRoot: function(onItem, onError)
         {
            // get the root pObject, we will do a get() and callback the result
            this.get("root").then(onItem, onError);
         },
         getLabel: function(pObject)
         {
            return pObject[this.labelAttr];
         },
         put: function(pObject, options)
         {
            //this.onChildrenChange(pObject, pObject[this.childrenAttr]);
            this.onChange(pObject);

            return Store.prototype.put.apply(this, arguments);
         },
         remove: function(objectId)
         {
            var obj = {};
            obj[this.idProperty] = objectId;
            this.onRemove(obj);

            return Store.prototype.remove.apply(this, arguments);
         },
         onRemove: function(pObject)
         {
            this.inherited(arguments);
            
            if(this.mObjectStoreWrapper)
            {
               this.mObjectStoreWrapper.onRemove(pObject);
               return;
            }
         },

         pasteItem: function(pChild, pOldParent, pNewParent, bCopy, insertIndex)
         {
            // get the full pOldParent object
            this.get(pOldParent.Id).then(dojo.hitch(this, function (pOldParent)
            {
               // get the full pNewParent object
               this.get(pNewParent.Id).then(dojo.hitch(this, function (pNewParent)
               {
                  // get the pOldParent's children and scan through it find the child object
                  var oldChildren = pOldParent[this.childrenAttr];
                  dojo.some(oldChildren, dojo.hitch(this, function(oldChild, i)
                  {
                     if (oldChild.Id == pChild.Id)
                     {
                        oldChildren.splice(i, 1);
                        return true;
                     }
                  }));
                  
                  this.put(pOldParent);
                  if (!pNewParent[this.childrenAttr])
                     pNewParent[this.childrenAttr] = [];
                  
                  pNewParent[this.childrenAttr].splice(insertIndex || 0, 0, pChild);
                  pChild.LinkedToInstantiatedClassId = pNewParent.Id;

                  try
                  {
                     //dojo toJson will fail with range error if parent is set
                     for (var i = 0; i < pNewParent[this.childrenAttr].length; i++)
                        pNewParent[this.childrenAttr][i].parent = null;
                     
                     this.put(pNewParent);
                     for (var y = 0; y < pNewParent[this.childrenAttr].length; y++)
                        pNewParent[this.childrenAttr][y].parent = pNewParent;
                  }
                  catch (error)
                  {
                     console.error(error);
                  }
               }));
            }));
         }

      });
   }
);
